﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SocketServer;
using System.Net.Sockets;
using System.Net;
using SkypengerApp.Data;

namespace SkypengerApp
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region VARIABLES ET INITIALISEURS

        private Diary _diary;
        private string _userName;
        private delegate void AddUserHandler(string name, string ip, int port, bool isOnline);
        private delegate void AddConversationHandler(string name, string ip, TcpClient socket);
        private List<string> _conversationsIP;
        private List<UserControls.Client> _contacts;
        private const int PORT = 8000;
        private SocketServer.SocketServer _socketserver;

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }

        // ÉVÈNEMENT: FIN DE CHARGEMENT DE LA VUE
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // Affichage seul de la fenêtre de connexion
            foreach (UIElement element in (this.Content as Grid).Children)
            {
                element.Visibility = System.Windows.Visibility.Hidden;
            }
            this.ConnWindow.Visibility = System.Windows.Visibility.Visible;

            this.ConnWindow.button1.Click += (sdr, evt) =>
            {
                if (ConnWindow.textBox1.Text != "")
                {
                    _userName = ConnWindow.textBox1.Text;
                    Load();
                }
            };
        }

        #endregion

        #region MÉTHODES PRIVÉES

        /// <summary>
        /// Loads this instance.
        /// </summary>
        private void Load()
        {
            // Fermeture de la fenêtre de connexion
            foreach (UIElement element in (this.Content as Grid).Children)
            {
                element.Visibility = System.Windows.Visibility.Visible;
            }
            this.ConnWindow.Visibility = System.Windows.Visibility.Collapsed;

            _conversationsIP = new List<string>();
            _contacts = new List<UserControls.Client>();

            _socketserver = SocketServer.SocketServer.GetInstance(_userName);
            // Abonnement aux évènements Server
            _socketserver.OnStateChange += (sdr, evt) =>
                {
                    this.LB_ConnState.Content = evt.Message;
                };

            _socketserver.OnClientRequest += (sdr, evt) =>
                {
                    if (_contacts.Exists(o => o.MyContact.IP == evt.IP))
                    {
                        UserControls.Client current = _contacts.Find(o => o.MyContact.IP == evt.IP);
                        if (current.IsOnline)
                            this.Dispatcher.BeginInvoke(new AddConversationHandler(this.AddConversation), evt.ClientName, evt.IP, evt.Socket);
                        else
                            this.Dispatcher.Invoke((Action)delegate() { current.SetState(true); });
                    }
                    else
                    {
                        _diary.AddContact(evt.ClientName, evt.IP, PORT);
                        this.Dispatcher.BeginInvoke(new AddUserHandler(this.AddContactIcone), evt.ClientName, evt.IP, PORT, true);
                    }
                };

            // Chargement des contacts
            _diary = DataHelper.Load();

            foreach (var contact in _diary.Contacts)
            {
                AddContactIcone(contact.Name, contact.IP, contact.Port, false);
            }

            // Démarrage du Server
            _socketserver.Start();

            
        }

        /// <summary>
        /// Adds the user.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="hashCode">The pos.</param>
        private void AddContactIcone(string name, string ipAddress, int port, bool isOnline)
        {
            try
            {
                UserControls.Client client = new UserControls.Client(name, ipAddress, port, _userName, isOnline);
                client.Margin = new Thickness(5);
                this.Utilisateurs.Content.Children.Add(client);
                _contacts.Add(client);
            }
            catch (Exception)
            {

            }
        }

        /// <summary>
        /// Adds the conversation.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="ip">The ip.</param>
        /// <param name="socket">The socket.</param>
        private void AddConversation(string name, string ip, TcpClient socket)
        {
            bool exist = false;

            try
            {
                foreach (string conversationIP in _conversationsIP)
                {
                    if (conversationIP == ip)
                    {
                        exist = true;
                    }
                }

                if (!exist)
                {
                    Conversation conversation = new Conversation(_userName, name, ip, socket);
                    conversation.Closed += (srd, evt) =>
                        {
                            _conversationsIP.Remove(ip);
                        };
                    _conversationsIP.Add(ip);
                    conversation.Show();
                }
            }
            catch (Exception)
            {
            }
        } 

        #endregion

        #region GESTION DU MENU PRINCIPAL

        // CHOIX D'AJOUT D'UN CONTACT
        private void MenuItem_Ajouter_Click(object sender, RoutedEventArgs e)
        {
            UserWindows.Ajouter_Utilis window = new UserWindows.Ajouter_Utilis();
            window.OnUserAdded += (sdr, evt) =>
                {
                    _diary.AddContact(evt.Name, evt.IP, evt.Port);
                    AddContactIcone(evt.Name, evt.IP, evt.Port, false);
                };
            window.Show();
        } 

        #endregion
    }
}
